using System;
using System.Collections.Generic;
using System.Text;

namespace Watchdog.Bll {
    public class DailySchedule : Schedule {

        #region [ Constructor's ]

        internal DailySchedule () { }

        internal DailySchedule ( Facade.Schedule schedule ) : base ( schedule ) { }

        #endregion

        #region [ Statics ]
        public static DailySchedule NewDailySchedule () {
            DailySchedule schedule = new DailySchedule ();
            return schedule;
        }
        #endregion

        #region [ Field Properties ]
        public new int Id {
            get { return intdata.Id; }
        }
        public new Test Test {
            get { return base.Test; }
            set { base.Test = value; }
        }
        public virtual bool Paused {
            get { return intdata.Paused; }
            set { intdata.Paused = value; }
        }
        public virtual DateTime DateStart {
            get { return intdata.DateStart; }
            set { intdata.DateStart = value; }
        }
        public virtual DateTime DateStop {
            get { return intdata.DateStop; }
            set { intdata.DateStop = value; }
        }
        public virtual Int16 RepeatInterval {
            get { return intdata.RepeatInterval; }
            set { intdata.RepeatInterval = value; }
        }
        public virtual DateTime NextRun {
            get { return intdata.NextRun; }
            set { intdata.NextRun = value; }
        }
        public virtual DateTime LastRun {
            get { return intdata.LastRun; }
            set { intdata.LastRun = value; }
        }
        #endregion

        #region [ Properties ]
        public TimeSpan HourStart {
            get {
                return TimeSpan.Parse ( intdata.HourStart );
            }
            set {
                intdata.HourStart = value.ToString ();
            }
        }
        public TimeSpan HourStop {
            get {
                return TimeSpan.Parse ( intdata.HourStop );
            }
            set {
                intdata.HourStop = value.ToString ();
            }
        }
        public ScheduleRepeatInterval RepeatType {
            get {
                return (ScheduleRepeatInterval)intdata.RepeatType;
            }
            set {
                intdata.RepeatType = (short)value.GetHashCode ();
            }
        }
        #endregion

        public DateTime GetNextExecuteTime ( DateTime date ) {
            DateTime Result = DateTime.MinValue;
            TimeSpan now = date.TimeOfDay;
            if (DateStart.Date.Add ( HourStart ) <= date && date <= DateStop.Date.Add ( HourStop )) {
                if (TimeSpan.Parse ( "00:00:00" ) <= date.TimeOfDay && date.TimeOfDay < HourStart) {
                    Result = date.Date.Add ( HourStart );
                }
                if (HourStart <= date.TimeOfDay && date.TimeOfDay <= HourStop) {
                    switch (RepeatType) {
                        case ScheduleRepeatInterval.Minutes:
                            // find the occurence that is in the future
                            Result = date.Date.Add ( HourStart );
                            while (Result <= date) {
                                Result = Result.AddMinutes ( RepeatInterval );
                                System.Diagnostics.Debug.WriteLine ( Result.ToString () );
                            }
                            // if the result is outside of the schedule we schedule it beginning of the next day
                            if (Result.Date == date.Date) {
                                // the next runtime is today
                                if (HourStart < Result.TimeOfDay && Result.TimeOfDay <= HourStop) {

                                } else {
                                    if (GetNextExecuteTime ( Result ) != DateTime.MaxValue)
                                        Result = date.Date.Add ( HourStart ).AddDays ( 1 );
                                    else
                                        Result = DateTime.MaxValue;
                                }
                            } else {
                                // the next runtime is tomorrow
                                Result = date.Date.Add ( HourStart ).AddDays ( 1 );
                            }
                            break;
                        case ScheduleRepeatInterval.Hours:
                            Result = date.Date.Add ( HourStart );
                            while (Result <= date) {
                                Result = Result.AddHours ( RepeatInterval );
                                System.Diagnostics.Debug.WriteLine ( Result.ToString () );
                            }
                            if (Result.Date == date.Date) {
                                // the next runtime is today
                                if (HourStart < Result.TimeOfDay && Result.TimeOfDay <= HourStop) {

                                } else {
                                    if (GetNextExecuteTime ( Result ) != DateTime.MaxValue)
                                        Result = date.Date.Add ( HourStart ).AddDays ( 1 );
                                    else
                                        Result = DateTime.MaxValue;
                                }
                            } else {
                                // the next runtime is tomorrow
                                Result = date.Date.Add ( HourStart ).AddDays ( 1 );
                            }
                            break;
                        case ScheduleRepeatInterval.None:
                            break;
                    }
                }
                if (HourStop < date.TimeOfDay && date.TimeOfDay <= TimeSpan.Parse ( "23:59:59" )) {
                    Result = date.Date.Add ( HourStart ).AddDays ( 1 );
                }
            } else {
                // The schedule does not have tor run anymore
                // So we return maxdate.
                Result = DateTime.MaxValue;
            }
            return Result;
        }

        public DateTime GetNextExecuteTime () {
            return GetNextExecuteTime ( DateTime.Now );
        }

        public DateTime SetNextExecuteTime () {
            NextRun = GetNextExecuteTime ( DateTime.Now );
            Update ();
            return NextRun;
        }
    }
}
